# -*- coding: UTF-8 -*-
# @Time : 2021/12/6 0006 16:15
# @Author : lyw
# @Remark :
import datetime
import re
import time

from db.common.IOTManager.UpsDevice.dev_select import UPSSelectDB, UPSListDB, UPSRetrieveDB, UPSTrendDB

try:
    from opm_pyirm import GetStatusById
except ImportError:
    try:
        from bsmiddle import GetStatusById
    except ImportError:
        def GetStatusById(*args):
            return 1, 2

from model.common.IOTManager.iot_base import SRoomIOTMiddleModel
from server.public.IOTManager.server_base import IOTBaseServer
from utils.classes.custom_exception import VerifyError
from index import _


class UPSSelectServer(IOTBaseServer):
    __db__ = UPSSelectDB
    __model__ = SRoomIOTMiddleModel

    s_run = "ups_run"
    s_state = "ups_state"
    run_state = "run_state"
    search = "ups_name"
    m_run = "run_mode"

    def __init__(self):
        super(UPSSelectServer, self).__init__()
        self.ups_temp = self.db.read_template()

    def device_info(self, device_list, state_dict: dict = None):
        """

        @param state_dict:
        @param device_list:
        @return:
        """
        res_device_data = []
        if state_dict is None:
            state_dict = {"state": 1}
        if state_dict["state"] != 2:
            state_dict["state"] = 1
        for device_data in device_list:
            status = GetStatusById(device_data["code"])
            if isinstance(status, int):
                status = status
            else:
                status = status[1]
            if state_dict is not None:
                if status != 1:
                    state_dict["state"] = 2
            device_info_dict = {"name": device_data["mxlabel"], "code": device_data["code"],
                                "state": self.set_state(status),
                                "local": self.db.get_local(
                                    self.model(device_type=self.db.device_type, iot_code=device_data["code"],
                                               sroom_code="")),
                                "alarm_info": "",
                                "mxdevicetype": device_data["mxdevicetype"]
                                }

            self.query_table_data(device_data, device_info_dict)

            res_device_data.append(device_info_dict)
        return res_device_data

    def query_table_data(self, ups_dev, ups_info_data):
        """
         查找 table 告警数据
        @param ups_dev: 设备的参数
        @param ups_info_data: 设备返回的数据
        @return:
        """
        # 当前的模板
        current_temp = self.ups_temp.get(ups_dev["mxdevicetype"].rsplit("\\", 1)[1])
        # 定义要取的参数

        res_query_field = [("input_voltage", ("输入", "电压")), ("output_voltage", ("输出", "电压")),
                           ("input_electricity", ("输入", "电流"))]
        ups_info_data["run_mode"] = ""
        if current_temp:
            temp_list = current_temp["run_mode"]
        else:
            temp_list = {"plugin": ""}

        for query_field in res_query_field:
            ups_info_data[query_field[0]] = []
            if current_temp is None:
                continue
            if not current_temp.get(query_field[0].split("_")[0]):
                continue
            # 获取第一个字典
            current_field = current_temp[query_field[0].split("_")[0]][0]

            for monitor_key, monitor_value in ups_dev["sub_monitor"].items():

                # 判断 参数是不是存在

                # 获取table 数据
                monitor_table_data = self.db.query_monitor_table_data(monitor_key)
                # 判断是不是空
                if not monitor_table_data:
                    continue
                # 增加运行信息
                if temp_list["plugin"] == monitor_value:
                    ups_info_data["run_mode"] = monitor_table_data[temp_list["key"]]
                # 判断是不是想要的告警信息
                if not re.search(current_field["key"], monitor_value):
                    continue

                # 遍历字段
                for field in current_field["monitor"]:

                    if not re.search(query_field[1][0], field["mxlabel"]) or not re.search(query_field[1][1],
                                                                                           field["mxlabel"]):
                        continue
                    if re.search("线", field["mxlabel"]):
                        continue

                    ups_info_data[query_field[0]].append({"phase": field["mxlabel"],
                                                          "data": monitor_table_data[field["key"]],
                                                          "unit": field["mxunit"],
                                                          "state": monitor_table_data["State"]})


class UPSListServer(IOTBaseServer):
    __db__ = UPSListDB

    def list(self):
        res_dict = self.db.query_device()
        for dev in res_dict:
            ups_status = GetStatusById(dev["code"])[1]

            dev["state"] = self.set_state(ups_status)

        return res_dict


class UPSRetrieveServer(UPSSelectServer):
    __db__ = UPSRetrieveDB

    def retrieve(self, code):
        """
        查询一个数据
        """
        ups_dev = self.db.retrieve(code)
        status = GetStatusById(ups_dev["code"])[1]

        ups_info_data = {"name": ups_dev["mxlabel"],
                         "code": ups_dev["code"],
                         "state": self.set_state(status),
                         "local": self.db.get_local(
                             self.model(device_type=self.db.device_type, iot_code=ups_dev["code"],
                                        sroom_code="")),
                         "update_time": ""}

        self.query_table_data(ups_dev, ups_info_data)
        return ups_info_data

    def query_table_data(self, ups_dev, ups_info_data):
        """
        获取table 表的信息
        @param ups_dev:
        @param ups_info_data:
        @return:
        """
        state = {0: 0, 1: 1, 2: 2, 3: 2, 4: 2, 5: 0}
        # 当前的模板
        current_temp = self.ups_temp.get(ups_dev["mxdevicetype"].rsplit("\\", 1)[1])
        if current_temp is None:
            return "设备模板不存在"
        ups_info_data["run_mode"] = ""
        for temp_key, temp_list in current_temp.items():
            if temp_key != "run_mode":
                ups_info_data["%s_info" % temp_key] = []
            for temp_value in temp_list:
                for monitor_key, monitor_value in ups_dev["sub_monitor"].items():
                    # 获取table 数据
                    monitor_table_data = self.db.query_monitor_table_data(monitor_key)
                    if not monitor_table_data:
                        continue
                    if temp_key == "run_mode":  # 如果是运行模式 获取数据跳过循环
                        if temp_list["plugin"] == monitor_value:
                            ups_info_data["run_mode"] = monitor_table_data[temp_list["key"]]
                        continue
                    # 判断 参数是不是存在
                    if temp_value["key"] != monitor_value:
                        continue
                    # 遍历字段
                    if ups_info_data["update_time"] < time.strftime("%Y-%m-%d %H:%M:%S",
                                                                    time.localtime(monitor_table_data["_CREATETIME_"])):
                        ups_info_data["update_time"] = time.strftime("%Y-%m-%d %H:%M:%S",
                                                                     time.localtime(monitor_table_data["_CREATETIME_"]))

                    for field in temp_value["monitor"]:
                        ups_info_data["%s_info" % temp_key].append({"phase": field["mxlabel"],
                                                                    "data": monitor_table_data[field["key"]],
                                                                    "unit": field["mxunit"],
                                                                    "state": state.get(monitor_table_data["State"], 0)})


class UPSTrendServer(UPSSelectServer):
    __db__ = UPSTrendDB

    def __init__(self):
        super().__init__()
        self.res_query_field = [("input_voltage", ("输入", "电压")),
                                ("input_electricity", ("输入", "电流")),
                                ("output_voltage", ("输出", "电压")),
                                ("output_electricity", ("输出", "电流")),
                                ("battery_voltage", ("电池", "电压")),
                                ("battery_temperature", ("电池", "温度")),
                                ]

    def list(self, **kwargs):
        """
        查找趋势数据
        @param kwargs:
        @return:
        """
        ups_dev = self.db.retrieve(kwargs["ups_code"])
        current_temp = self.ups_temp.get(ups_dev["mxdevicetype"].rsplit("\\", 1)[1])
        if current_temp is None:
            raise VerifyError("设备模板不存在")
        if kwargs.get("comparison"):
            # 获取对比参数
            return self.comparison_data(kwargs["comparison"], current_temp, ups_dev)

        if kwargs.get("alert_time") in ("0", "1", "3", "7"):
            end_time = datetime.datetime.now()
            if kwargs["alert_time"] == "0":
                start_time = datetime.datetime.fromtimestamp(time.mktime(datetime.date.today().timetuple()))
            else:
                start_time = end_time - datetime.timedelta(days=int(kwargs["alert_time"]))

        else:
            if kwargs.get("start_time") and kwargs.get("end_time"):
                start_time = datetime.datetime.strptime(kwargs["start_time"].replace("+", " "), "%Y-%m-%d %H:%M:%S")
                end_time = datetime.datetime.strptime(kwargs["end_time"].replace("+", " "), "%Y-%m-%d %H:%M:%S")
            else:
                raise VerifyError("alert_time 参数 或者 start_time 和end_time 参数错误")
        if start_time > end_time:
            raise VerifyError("开始时间大于结束时间")
        # 定义要取的参数
        ups_info_data = {}
        for query_field in self.res_query_field:
            # 遍历字段
            ups_info_data[query_field[0]] = {"name": "".join(query_field[1]), "label": [],
                                             "history": []}
            if not current_temp.get(query_field[0].split("_")[0]):
                continue
            # 获取第一个字典
            current_field = current_temp[query_field[0].split("_")[0]][0]

            for monitor_key, monitor_value in ups_dev["sub_monitor"].items():

                # 判断 参数是不是存在
                if not re.search(current_field["key"], monitor_value):
                    continue
                # 获取table 数据

                label_list = self.query_field(query_field, current_field)
                history = self.query_monitor_data(monitor_key, start_time, end_time, label_list)
                # 获取数据
                if label_list and history:
                    ups_info_data[query_field[0]] = {"name": "".join(query_field[1]), "label": label_list,
                                                     "history": history}

        return ups_info_data

    @staticmethod
    def query_field(query_field, current_field):
        """
        过滤字段
        @param query_field:
        @param current_field:
        @return:
        """
        label = []
        for field in current_field["monitor"]:

            if not re.search(query_field[1][0], field["mxlabel"]) or not re.search(query_field[1][1],
                                                                                   field["mxlabel"]):
                continue
            if re.search("线", field["mxlabel"]):
                continue
            label.append({"name": field["mxlabel"].replace(query_field[1][0], ""), "property": field["key"],
                          "unit": field["mxunit"], })
        return label

    def comparison_data(self, operation, current_temp, ups_dev):
        """
        查询对比的数据
        @param operation:
        @param ups_dev:
        @param current_temp:
        @return:
        """
        operation_dict = {"day": {"history": ({"days": 2}, "昨天"), "current": ({"days": 1}, "当天")},
                          "week": {"history": ({"weeks": 2}, "上周"), "current": ({"days": 1}, "本周")},
                          "month": {"history": ({"days": 30}, "上月"), "current": ({"days": 30}, "本月")}}
        ups_info_data = {}
        if not operation_dict.get(operation):
            raise VerifyError(_("operation 参数错误"))

        end_time = datetime.datetime.now()
        start_time = end_time - datetime.timedelta(**operation_dict[operation]["current"][0])
        # history_start = end_time
        history_end = start_time
        # history_end = end_time - datetime.timedelta(**operation_dict[operation]["history"])
        history_start = end_time - datetime.timedelta(**operation_dict[operation]["history"][0])

        for query_field in self.res_query_field:

            ups_info_data[query_field[0]] = {"name": "".join(query_field[1]), "label": [], "contrast": [],
                                             "current": [], "history": []}
            if not current_temp.get(query_field[0].split("_")[0]):
                continue
            # 获取第一个字典
            current_field = current_temp[query_field[0].split("_")[0]][0]

            for monitor_key, monitor_value in ups_dev["sub_monitor"].items():

                # 判断 参数是不是存在
                if not re.search(current_field["key"], monitor_value):
                    continue
                # 获取table 数据

                # 遍历字段
                label_list = self.query_field(query_field, current_field)
                # 获取当前数据
                current = self.query_monitor_data(monitor_key, start_time, end_time, label_list)
                # 获取对比数据
                history = self.query_monitor_data(monitor_key, history_start, history_end, label_list)

                if label_list and current and history:
                    ups_info_data[query_field[0]] = {"name": "".join(query_field[1]), "label": label_list,
                                                     "contrast": self.join_contrast(operation_dict[operation]),
                                                     "current": current, "history": history}
        return ups_info_data

    @staticmethod
    def join_contrast(label):
        """
        拼接 名称
        """
        res_list = []
        for k, v in label.items():
            res_list.append({"name": v[1], "property": k})
        return res_list

    def query_monitor_data(self, monitor_key, start_time, end_time, label_list):
        """
        查询数据库数据
        @param monitor_key:
        @param start_time:
        @param end_time:
        @param label_list:
        @return:
        """
        monitor_table_data = self.db.query_monitor_table_data(code=monitor_key, count=100,
                                                              start_time=int(start_time.timestamp()),
                                                              end_time=int(end_time.timestamp())
                                                              )
        if not monitor_table_data:
            return None
        history = []
        for monitor_data in monitor_table_data:
            # 遍历所有的table 表
            value_list = []
            history.append(
                {"date_time": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(monitor_data["_CREATETIME_"])),
                 "value": value_list})
            for label_dict in label_list:
                value_list.append({"property": label_dict["property"],
                                   "value": monitor_data[label_dict["property"]]})
        return history
